<%@ Page Language="vb" AutoEventWireup="true" Debug="true"%>  
<%@ Import Namespace="System.IO" %>  
<script language="VB" runat="server">
    
    '   createclass.aspx
    '
    '   part of WHMCSdotnet (http://whmcsdotnet.wordpress.com)
    '
    '   Copyright (C) 2009-2011 Mark Castle <markcastle@gmail.com>
    '   All rights reserved. 
    '   Copyright (C) 2009-2011 Secura Hosting Ltd <code@securahosting.com>.
    '   All rights reserved.
    ' 
    '   Redistribution and use in source and binary forms, with or without modification,
    '   are permitted provided that the following conditions are met:
    ' 
    '   - Redistributions of source code must  retain  the  above copyright notice, this
    '     list of conditions and the following disclaimer.
    ' 
    '   - Redistributions in binary form  must  reproduce the  above  copyright  notice,
    '     this list of conditions  and  the  following  disclaimer in  the documentation
    '     and/or other materials provided with the distribution.
    ' 
    '   - Neither  the  name  of  Secura Hosting Ltd, Mark Castle  nor the names of  its
    '     contributors may be used to endorse or  promote  products  derived  from  this
    '     software without specific prior written permission.
    ' 
    '   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    '   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT  NOT  LIMITED TO, THE IMPLIED
    '   WARRANTIES  OF  MERCHANTABILITY   AND  FITNESS  FOR  A  PARTICULAR  PURPOSE  ARE
    '   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
    '   ANY DIRECT, INDIRECT, INCIDENTAL,  SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    '   (INCLUDING, BUT NOT LIMITED TO,  PROCUREMENT  OF  SUBSTITUTE  GOODS OR SERVICES;
    '   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  HOWEVER  CAUSED AND ON
    '   ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT  LIABILITY,  OR TORT
    '   (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING  IN  ANY WAY OUT OF THE USE OF THIS
    '   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    '   Please note this is very old code that needs refactoring and cleaning up - MC
    ' Constants
    Private Const _Setting_IncludeChangedProperties As Boolean = True
    Private Const _Setting_Version As String = "Secura Collection Class Builder Version 2.5 (for WHMCS)"
    Private Const _Setting_TemplateFile As String = "collectionclasstemplate2.5.txt"
    Private Const _DefaultNamespace As String = "Secura.WHMCS"
    Private Const _InheritsText As String = "Secura.WHMCS.APIBaseType"
    
    ' The Known data types and default values for our collections.
    ' PHPs Associative Arrays would be much easier :-(
    Private KnownTypes As String = "Array=arr,;Boolean=bln,False;Byte=byt,0;Char=chr,"""";DateTime=dtm,DateTime.Now();Decimal=dec,0;Double=dbl,0;Integer=int,0;Int32=int,0;Long=lng,0;Object=obj,;Short=shr,0;Single=sng,0;String=str,"""""
    Private DataTypesCol As New System.Collections.Specialized.NameValueCollection()
    Private DataTypesKey As String
	
    ''' <summary>
    ''' Page_Load Event
    ''' </summary>
    ''' <param name="obj"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
	Sub Page_Load(obj AS object, e AS eventargs)
  		Dim intCounter As Integer = 0
  		
		txtOutPut.EnableViewState = False
		divDebug.EnableViewState = False
        divDebug.Visible = False
        
        If Not (IsPostBack) Then
            ' Initialise everything on first use
            Validate()
            ViewState("PropertiesCount") = 0
            ViewState("MethodsCount") = 0
            txtOutPut.Visible = False
            txtNamespace.Text = _DefaultNamespace
            divClass1.InnerHtml &= "<b>Collection:</b><br/>" & vbCrLf
            InheritsTextbox.Text = _InheritsText
            chkForWHMCSAPI.Checked = True
        Else
            If ViewState("PropertiesCount") > 0 Then
                For intCounter = 1 To ViewState("PropertiesCount")
                    AddControl("Property", intCounter, plhProperties1, "Property", True)
                Next
            End If
			
            If ViewState("MethodsCount") > 0 Then
                For intCounter = 1 To ViewState("MethodsCount")
                    AddControl("Method", intCounter, plhMethods1, "Method", False)
                Next
            End If
        End If
    End Sub
    
    ''' <summary>
    ''' InitErrors
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub InitErrors()
        lblError.Text = ""
        lblError.Visible = False
    End Sub
    
    ''' <summary>
    ''' Display errors
    ''' </summary>
    ''' <param name="ErrorText"></param>
    ''' <remarks></remarks>
    Private Sub ShowError(ByVal ErrorText As String)
        lblError.Text = ErrorText & "<br/>"
        lblError.Visible = True
        Trace.Write("Error", ErrorText)
    End Sub

    ''' <summary>
    ''' Create Class Button Event Handler
    ''' </summary>
    ''' <param name="Sender"></param>
    ''' <param name="E"></param>
    ''' <remarks></remarks>
    Private Sub btnCreateClass_Click(ByVal Sender As Object, ByVal E As EventArgs)
        CreateCollectionClass(chkForASP.Checked, chkDebugEnabled.Checked, chkForWHMCSAPI.Checked)
    End Sub
    
    ''' <summary>
    ''' Create the Collection Class
    ''' </summary>
    ''' <param name="ForASP"></param>
    ''' <param name="DebugEnabled"></param>
    ''' <param name="IsForWHMCSAPI"></param>
    ''' <remarks></remarks>
    Public Sub CreateCollectionClass(Optional ByVal ForASP As Boolean = True, _
                                    Optional ByVal DebugEnabled As Boolean = True, _
                                    Optional ByVal IsForWHMCSAPI As Boolean = False)

        Dim ClassText As New StringBuilder()
        Dim PropertiesText As New StringBuilder()
        Dim PropertyDeclarations As New StringBuilder()
        Dim Methods As New StringBuilder()
        Dim EnumText As New StringBuilder()
        Dim CompareText As New StringBuilder()
        Dim ConstructorParams As New StringBuilder()
        Dim ConstructorAssigns As New StringBuilder()
        Dim OverloadedConstructor As New StringBuilder()
        Dim Counter As Integer = 0
        Dim PropertyName As String = ""
        Dim IsReadOnly As Boolean = False
        Dim ReturnType As String = ""
        Dim MethodName As String = ""
        Dim IsFunction As Boolean = False
        
        DataTypesCol = StoreNameValues(KnownTypes)

        'Dim strTemplateFile As String = Server.Mappath("collectionclasstemplate2.txt")
        'divClass1.innerHTML = "<b>test</b><br/>" & vbCrLf
        'divClass1.Visible = True

        lblClassSaveAs.Text = "Save As: <b>" & txtNamespace.Text & "." & txtClassName.Text & ".aspx.vb" & "</b>" & vbCrLf
        lblClassSaveAs.Visible = True
			
        ' ClassText.Append(Secura.WHMCS.APIHelperUtils.GetFileContents(Server.MapPath(IIf(IsForWHMCSAPI, _Setting_TemplateFile_WHMCS, _Setting_TemplateFile))))
        ' ClassText.Append(Secura.WHMCS.APIHelperUtils.GetFileContents(Server.MapPath(_Setting_TemplateFile)))
        ClassText.Append(My.Computer.FileSystem.ReadAllText(Server.MapPath(_Setting_TemplateFile)))
        
        ClassText.Replace("[~Namespace~]", txtNamespace.Text)
        If txtNamespace.Text <> "" Then
            ClassText.Replace("[~Namespace Start~]", "Namespace")
            ClassText.Replace("[~Namespace End~]", "End Namespace")
        Else : ClassText.Replace("[~Namespace Start~]", "")
            ClassText.Replace("[~Namespace End~]", "")
        End If
				
        ClassText.Replace("[~ClassName~]", txtClassName.Text)
        
        ClassText.Replace("[~ScriptName~]", "http://" & Request.ServerVariables("SERVER_NAME") & Request.ServerVariables("SCRIPT_NAME"))
			
        divDebug.InnerHtml &= "Properties: " & ViewState("PropertiesCount") & "<br/>" & vbCrLf

        ' divDebug.innerHTML &= "Controls: " 	& plhMethods1.Controls.Count() & "<br/>" & vbCrLf
        'Dim objControl As Control
        'For Each objControl In plhMethods1.Controls
        '	divDebug.innerHTML &= "&nbsp;&nbsp;Property:" & objControl.Id & "|" & objControl.ToString() & "<br/>" & vbCrLf
        'Next

        ' -----------------------------------------------
        ' -- Get Properties
        ' -----------------------------------------------
        For Counter = 1 To ViewState("PropertiesCount")
            PropertyName = ""
            IsReadOnly = False
            ReturnType = ""
            If GetProperty(Counter, PropertyName, IsReadOnly, ReturnType) Then
                If PropertyName <> "" Then
                    PropertiesText.Append(BuildProperty(PropertyName, IsReadOnly, ReturnType))
                    PropertyDeclarations.Append(BuildPropertyDeclarations(PropertyName, IsReadOnly, ReturnType))
						
                    ' The default comparison property used in sorting
                    If Counter = 1 Then
                        ClassText.Replace("[~SortByDefaultEnum~]", PropertyName)
                    End If
						
                    ' This is for the sorting enum & Compare case statements
                    EnumText.Append("        " & PropertyName & IIf(Counter <> ViewState("PropertiesCount"), vbCrLf, ""))
                    CompareText.Append("                Case SortByType." & PropertyName & vbCrLf)
                    CompareText.Append("                    Return " & PropertyName & ".CompareTo(objTemp." & PropertyName & ")" & vbCrLf)
						
                    If Not (IsReadOnly) Then
                        ConstructorParams.Append("ByVal " & PropertyName & " As " & ReturnType & "" & IIf(Counter <> ViewState("PropertiesCount"), ", ", ""))
                        ConstructorAssigns.Append("            _" & PropertyName & " = " & PropertyName & IIf(Counter <> ViewState("PropertiesCount"), vbCrLf, ""))
                        ' ConstructorAssigns.Append("            " & GetIndexedValue(ReturnType, DataTypesCol, 0) & PropertyName & " = " & PropertyName & Iif(Counter <> ViewState("PropertiesCount"), vbCrLf, ""))
                    End If
                End If
            End If
				
        Next
        divDebug.InnerHtml &= "Properties:<hr/>" & Replace(PropertiesText.ToString(), vbCrLf, "<br/>" & vbCrLf) & "<hr/>" & vbCrLf


        OverloadedConstructor.Append(BuildConstructor(ConstructorParams.ToString(), ConstructorAssigns.ToString()))

        ' -----------------------------------------------
        ' -- Get Methods
        ' -----------------------------------------------
        divDebug.InnerHtml &= "Methods: " & ViewState("MethodsCount") & "<br/>" & vbCrLf

        For Counter = 1 To ViewState("MethodsCount")
            MethodName = ""
            IsFunction = False
            ReturnType = ""
            If GetMethod(Counter, MethodName, IsFunction, ReturnType) Then
                If MethodName <> "" Then
                    Methods.Append(BuildMethod(MethodName, IsFunction, ReturnType))
                End If
            End If
        Next
			
        ' -----------------------------------------------
        ' -- Which Plural are we going to use for the collection...?
        ' -- Either s or Collection... eg SimpleObjects or SimpleObjectCollection
        ' -----------------------------------------------			
        Trace.Write("Plural: ", ddlPlural.SelectedItem.Value)
			
        ' -----------------------------------------------
        ' -- Now Put it all together...
        ' -----------------------------------------------
        ClassText.Replace("[~PropertyDeclarations~]", PropertyDeclarations.ToString())
        ClassText.Replace("[~Properties~]", PropertiesText.ToString())
        ClassText.Replace("[~PublicMethods~]", Methods.ToString())
        ClassText.Replace("[~SortByEnum~]", EnumText.ToString())
        ClassText.Replace("[~CompareCaseStatements~]", CompareText.ToString())
        ClassText.Replace("[~OverloadedConstructor~]", OverloadedConstructor.ToString())
        ClassText.Replace("[~CollectionPlural~]", ddlPlural.SelectedItem.Value.ToString())
			
        If DebugEnabled Then
            If ForASP Then
                ClassText.Replace("[~DebugVB~]", "'")
                ClassText.Replace("[~DebugAsp~]", "")
            Else
                ClassText.Replace("[~DebugVB~]", "")
                ClassText.Replace("[~DebugAsp~]", "'")
            End If
        Else
            ClassText.Replace("[~DebugVB~]", "'")
            ClassText.Replace("[~DebugAsp~]", "'")
        End If
        
        If InheritsTextbox.Text <> "" Then
            ClassText.Replace("[~ClassInherits~]", "Inherits " & InheritsTextbox.Text)
        Else
            ClassText.Replace("[~ClassInherits~]", "")
        End If
        
        ' Write Out the Final Class
        txtOutPut.Value = ClassText.ToString()
        txtOutPut.Visible = True
    End Sub
    
    ''' <summary>
    ''' Build the property declarations string
    ''' </summary>
    ''' <param name="PropertyName"></param>
    ''' <param name="IsReadOnly"></param>
    ''' <param name="ReturnType"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function BuildPropertyDeclarations(ByVal PropertyName As String, ByVal IsReadOnly As Boolean, ByVal ReturnType As String) As String
        Dim strProperty As New StringBuilder()
        strProperty.Append("    Private [~PropertyTypeShort~][~PropertyName~]		As [~PropertyReturnType~] 	[~PropertyDefaultValue~]" & vbCrLf)
        strProperty.Replace("[~PropertyName~]", PropertyName)
        strProperty.Replace("[~PropertyReturnType~]", ReturnType)
        strProperty.Replace("[~PropertyTypeShort~]", "_")
        ' strProperty.Replace("[~PropertyTypeShort~]", GetIndexedValue(ReturnType, DataTypesCol, 0))	
		
        Dim strPropVal As String
		
        Dim strDefault As String
        strDefault = GetIndexedValue(ReturnType, DataTypesCol, 1)
        If strDefault <> "" Then
            strPropVal = " = " & strDefault
        Else
            strPropVal = ""
        End If
		
        'Select Case LCase(ReturnType)
        '	Case "string"
        '		strPropVal = " = """""
        '	Case "integer"
        '		strPropVal = " = 0"
        '	Case "boolean"
        '		strPropVal = " = False"
        '	Case Else
        '		strPropVal = ""
        'End Select
        strProperty.Replace("[~PropertyDefaultValue~]", strPropVal)
        Return strProperty.ToString()
    End Function
    
    ''' <summary>
    ''' Build the Constructor String
    ''' </summary>
    ''' <param name="ConstructorParams"></param>
    ''' <param name="ConstructorAssigns"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function BuildConstructor(ByVal ConstructorParams As String, ByVal ConstructorAssigns As String) As String
        Dim strConstructor As New StringBuilder()
        strConstructor.Append("    Public Sub New([~ConstructorParams~])" & vbCrLf)
        strConstructor.Append("[~ConstructorAssigns~]" & vbCrLf)
        strConstructor.Append("    End Sub" & vbCrLf)
		
        ' Strip any Trailing commas
        ConstructorParams = Trim(ConstructorParams)
        If Right(ConstructorParams, 1) = "," Then
            ConstructorParams = Left(ConstructorParams, Len(ConstructorParams) - 1)
        End If

        strConstructor.Replace("[~ConstructorParams~]", ConstructorParams)
        strConstructor.Replace("[~ConstructorAssigns~]", ConstructorAssigns)

        Return strConstructor.ToString()
    End Function
    
    ''' <summary>
    ''' Build the Properties String
    ''' </summary>
    ''' <param name="PropertyName"></param>
    ''' <param name="IsReadOnly"></param>
    ''' <param name="ReturnType"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function BuildProperty(ByVal PropertyName As String, _
            ByVal IsReadOnly As String, _
            ByVal ReturnType As String) As String
    
        Dim PropertyString As New StringBuilder()
    
        If IsReadOnly Then
            PropertyString.Append("    ''' <summary>" & vbCrLf)
            PropertyString.Append("    ''' [~PropertyName~] Property (readonly)" & vbCrLf)
            PropertyString.Append("    ''' </summary>" & vbCrLf)
            PropertyString.Append("    ''' <value></value>" & vbCrLf)
            PropertyString.Append("    ''' <returns></returns>" & vbCrLf)
            PropertyString.Append("    ''' <remarks></remarks>" & vbCrLf)
            
            PropertyString.Append("    Public Readonly Property [~PropertyName~]() As [~PropertyReturnType~]" & vbCrLf)
            PropertyString.Append("        Get" & vbCrLf)
            PropertyString.Append("            Return [~PropertyTypeShort~][~PropertyName~]" & vbCrLf)
            PropertyString.Append("        End Get" & vbCrLf)
            PropertyString.Append("    End Property" & vbCrLf)
            PropertyString.Append("        " & vbCrLf)
        Else
            PropertyString.Append("    ''' <summary>" & vbCrLf)
            PropertyString.Append("    ''' [~PropertyName~] Property (r/w)" & vbCrLf)
            PropertyString.Append("    ''' </summary>" & vbCrLf)
            PropertyString.Append("    ''' <value></value>" & vbCrLf)
            PropertyString.Append("    ''' <returns></returns>" & vbCrLf)
            PropertyString.Append("    ''' <remarks></remarks>" & vbCrLf)
            
            PropertyString.Append("    Public Property [~PropertyName~]() As [~PropertyReturnType~] " & vbCrLf)
            PropertyString.Append("        Get" & vbCrLf)
            PropertyString.Append("            Return [~PropertyTypeShort~][~PropertyName~] " & vbCrLf)
            PropertyString.Append("        End Get" & vbCrLf)
            PropertyString.Append("        " & vbCrLf)
            PropertyString.Append("        Set(ByVal Value As [~PropertyReturnType~] )" & vbCrLf)
            PropertyString.Append("            [~PropertyTypeShort~][~PropertyName~] = Value" & vbCrLf)
            PropertyString.Append("        End Set" & vbCrLf)
            PropertyString.Append("    End Property" & vbCrLf)
            PropertyString.Append("        " & vbCrLf)
        End If
		
        PropertyString.Replace("[~PropertyName~]", PropertyName)
        PropertyString.Replace("[~PropertyReturnType~]", ReturnType)
        ' strProperty.Replace("[~PropertyTypeShort~]", GetIndexedValue(ReturnType, DataTypesCol, 0))
        PropertyString.Replace("[~PropertyTypeShort~]", "_")
    	
        Return PropertyString.ToString()
    End Function
    
    ''' <summary>
    ''' Build the Method Strings
    ''' </summary>
    ''' <param name="MethodName"></param>
    ''' <param name="IsFunction"></param>
    ''' <param name="ReturnType"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function BuildMethod(ByVal MethodName As String, _
            ByVal IsFunction As Boolean, _
            ByVal ReturnType As String) As String
        Dim Method As New StringBuilder()
        If IsFunction Then

            Method.Append("    ''' <summary>" & vbCrLf)
            Method.Append("    ''' [~MethodName~] Method" & vbCrLf)
            Method.Append("    ''' </summary>" & vbCrLf)
            Method.Append("    ''' <value></value>" & vbCrLf)
            Method.Append("    ''' <returns>[~MethodReturnType~]</returns>" & vbCrLf)
            Method.Append("    ''' <remarks></remarks>" & vbCrLf)
            Method.Append("    Public Function [~MethodName~]( ) As [~MethodReturnType~]" & vbCrLf)
            Method.Append("    " & vbCrLf)
            Method.Append("    " & vbCrLf)
            Method.Append("    End Function" & vbCrLf)
            Method.Append("    " & vbCrLf)

        Else
            Method.Append("    ''' <summary>" & vbCrLf)
            Method.Append("    ''' [~MethodName~] Method" & vbCrLf)
            Method.Append("    ''' </summary>" & vbCrLf)
            Method.Append("    ''' <value></value>" & vbCrLf)
            Method.Append("    ''' <returns></returns>" & vbCrLf)
            Method.Append("    ''' <remarks></remarks>" & vbCrLf)
            Method.Append("    Public Sub [~MethodName~]( )" & vbCrLf)
            Method.Append("    " & vbCrLf)
            Method.Append("    " & vbCrLf)
            Method.Append("    End Sub" & vbCrLf)
            Method.Append("    " & vbCrLf)
        End If
	    
        Method.Replace("[~MethodName~]", MethodName)
        Method.Replace("[~MethodReturnType~]", ReturnType)
        ' Method.Replace("[~PropertyTypeShort~]", GetIndexedValue(ReturnType, DataTypesCol, 0))
	    
        Return Method.ToString()
    End Function
    
    'Public Function ShortTypeLookup(ByVal strType As String, ByVal KnownTypes As String) As String
    
    '    Dim KnownTypesArr() As String
    '    Dim arrTypes
    '    KnownTypesArr = Split(KnownTypes, ",")
    '    Select Case LCase(Trim(strType))
    '        Case "array"
    '        Case "string"
    '        Case "integer"
    '        Case "boolean"
    '    End Select
    'End Function
    
    ''' <summary>
    ''' GetProperty
    ''' </summary>
    ''' <param name="intItem"></param>
    ''' <param name="PropertyName"></param>
    ''' <param name="IsReadOnly"></param>
    ''' <param name="ReturnType"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetProperty(ByVal intItem As Integer, _
            ByRef PropertyName As String, _
            ByRef IsReadOnly As Boolean, _
            ByRef ReturnType As String) As Boolean
	
        PropertyName = Trim(GetTextControlValue("txtProperty" & CStr(intItem)))
        IsReadOnly = IIf(Trim(GetDDLControlValue("ddlPropertyType" & CStr(intItem))) = "R", True, False)
        ReturnType = Trim(GetDDLControlValue("ddlPropertyReturns" & CStr(intItem)))
        Return True
    End Function
    
    ''' <summary>
    ''' GetMethod
    ''' </summary>
    ''' <param name="intItem"></param>
    ''' <param name="MethodName"></param>
    ''' <param name="IsFunction"></param>
    ''' <param name="ReturnType"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetMethod(ByVal intItem As Integer, _
                ByRef MethodName As String, _
                ByRef IsFunction As Boolean, _
                ByRef ReturnType As String) As Boolean

        MethodName = Trim(GetTextControlValue("txtMethod" & CStr(intItem)))
        IsFunction = IIf(Trim(GetDDLControlValue("ddlMethodType" & CStr(intItem))) = "F", True, False)
        ReturnType = Trim(GetDDLControlValue("ddlMethodReturns" & CStr(intItem)))

        Return True
    End Function
    
    ''' <summary>
    ''' Return the Text Value from a Control of a given name
    ''' </summary>
    ''' <param name="ControlName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetTextControlValue(ByVal ControlName As String) As String
        Dim txtControl As TextBox = FindControl(ControlName)
        If Not (txtControl Is Nothing) Then
            'divDebug.innerHTML &= "&nbsp;&nbsp;" & ControlName & ".Text=<b>" & txtControl.Text & "</b><br/>" & vbCrLf
            Return txtControl.Text
        Else
            'divDebug.innerHTML &= "&nbsp;&nbsp;" & ControlName & ".Text=<b>Nothing</b><br/>" & vbCrLf
            Return ""
        End If
    End Function

    ''' <summary>
    ''' Get the SelectedValue from a Drop down list control of a given name
    ''' </summary>
    ''' <param name="ControlName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetDDLControlValue(ByVal ControlName As String) As String
        Dim ddlControl As DropDownList = FindControl(ControlName)
        If Not (ddlControl Is Nothing) Then
            'divDebug.innerHTML &= "&nbsp;&nbsp;" & ControlName & ".SelectedValue=<b>" & ddlControl.SelectedValue & "</b><br/>" & vbCrLf
            Return ddlControl.SelectedValue
        Else
            'divDebug.innerHTML &= "&nbsp;&nbsp;" & ControlName & ".SelectedValue=<b>Nothing</b><br/>" & vbCrLf
            Return ""
        End If
    End Function
    
    ''' <summary>
    ''' ParseSimpleControls (not used)
    ''' </summary>
    ''' <param name="colControls"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ParseSimpleControls(ByRef colControls As ControlCollection) As Hashtable
        Dim objControl As Control
        Dim hshControls As New Hashtable()
        If colControls.Count() > 0 Then
            For Each objControl In colControls
                'If Not(IsNull(objControl.Id)) Then
                Try
                    Select Case LCase(Left(objControl.ID.ToString(), 3))
                        Case "txt", "rdo", "ddl"
                            ' hshControls.Add(objControl.Id.ToString(), objControl.Text.ToString())
                    End Select
                    'End If
                Catch
                    ' Discard it --> It is probably Null (eg has no id, so we're not interested in it anyway)
                End Try
            Next
        End If
        Return hshControls
    End Function
    
    ''' <summary>
    ''' Add Property Button Event Handler
    ''' </summary>
    ''' <param name="Sender"></param>
    ''' <param name="E"></param>
    ''' <remarks></remarks>
    Private Sub btnAddProperty_Click(ByVal Sender As Object, ByVal E As EventArgs)
        ViewState("PropertiesCount") += 1
        AddControl("Property", ViewState("PropertiesCount"), plhProperties1, "Property", True)
    End Sub

    ''' <summary>
    ''' Add Method Button Event Handler
    ''' </summary>
    ''' <param name="Sender"></param>
    ''' <param name="E"></param>
    ''' <remarks></remarks>
    Private Sub btnAddMethod_Click(ByVal Sender As Object, ByVal E As EventArgs)
        ViewState("MethodsCount") += 1
        AddControl("Method", ViewState("MethodsCount"), plhMethods1, "Method", False)
    End Sub

    ''' <summary>
    ''' Add a Control of a given type to a placeholder  
    ''' </summary>
    ''' <param name="NamePrefix"></param>
    ''' <param name="FieldNum"></param>
    ''' <param name="plhControl"></param>
    ''' <param name="ControlName"></param>
    ''' <param name="IsProperty"></param>
    ''' <remarks></remarks>
    Sub AddControl(ByVal NamePrefix As String, _
                    ByVal FieldNum As String, _
                    ByRef plhControl As PlaceHolder, _
                    ByVal ControlName As String, _
                    ByVal IsProperty As Boolean)
	
        Dim litLabel As LiteralControl
        Dim txtControl As TextBox
        Dim ddlControl As DropDownList
	
        DataTypesCol = StoreNameValues(KnownTypes)
	
        ' Add Literal Control
        litLabel = New LiteralControl
        litLabel.Text = "<p><b>" & NamePrefix & " " & FieldNum & " Name:</b> "
        plhControl.Controls.Add(litLabel)
	
        ' Add TextBox Control
        txtControl = New TextBox
        txtControl.ID = "txt" & ControlName & FieldNum
        plhControl.Controls.Add(txtControl)
	  
        ' Add Literal Control
        litLabel = New LiteralControl
        litLabel.Text = "&nbsp;&nbsp;<b>Type:</b> " ' (" & Iif(IsProperty, "Property", "Method") & ")"
        plhControl.Controls.Add(litLabel)
	  
        If IsProperty Then
            ddlControl = New DropDownList
            ddlControl.ID = "ddl" & ControlName & "Type" & FieldNum
            ddlControl.Items.Add(New ListItem("Read Write", "RW"))
            ddlControl.Items.Add(New ListItem("Read Only", "R"))
            plhControl.Controls.Add(ddlControl)
        Else
            ddlControl = New DropDownList
            ddlControl.ID = "ddl" & ControlName & "Type" & FieldNum
            ddlControl.Items.Add(New ListItem("Function", "F"))
            ddlControl.Items.Add(New ListItem("Subroutine", "S"))
            plhControl.Controls.Add(ddlControl)
        End If

        ' Add Literal Control
        litLabel = New LiteralControl
        litLabel.Text = "&nbsp;&nbsp;<b>Returns:</b> " ' (" & Iif(IsProperty, "Property", "Method") & ")"
        plhControl.Controls.Add(litLabel)

        ddlControl = New DropDownList
        ddlControl.ID = "ddl" & ControlName & "Returns" & FieldNum
		
        For Each DataTypesKey In DataTypesCol
            ddlControl.Items.Add(New ListItem(DataTypesKey))
            ' lblOutput.Text &= "DataTypesKey=" & DataTypesKey & " | colNameValue(DataTypesKey)=" & colNameValue(DataTypesKey).ToString() & "<br/>" & vbCrLf
        Next

        plhControl.Controls.Add(ddlControl)
	 
    End Sub
    
    ''' <summary>
    ''' Convert a Name Value Serialised String to a NameValueCollection
    ''' Expects a String in the format... "KEY1=String1,String2;KEY2=String1,String2; etc etc    
    ''' </summary>
    ''' <param name="ToStore"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function StoreNameValues(ByVal ToStore As String) As System.Collections.Specialized.NameValueCollection
        Dim arrSplitString As String() = ToStore.Split(New Char() {";"c, "="c})
        Dim colNameValue As New System.Collections.Specialized.NameValueCollection()
        Dim Counter As Integer
        For Counter = 0 To arrSplitString.Length - 2 Step 2
            colNameValue.Add(arrSplitString(Counter), arrSplitString(Counter + 1))
        Next
        Return colNameValue
    End Function

    ''' <summary>
    ''' Get an Item at Index from a NameValueCollection
    ''' Probably not the best way to do this.    
    ''' </summary>
    ''' <param name="DataTypesKey"></param>
    ''' <param name="DataTypesCol"></param>
    ''' <param name="intIndex"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetIndexedValue(ByVal DataTypesKey As String, _
                                     ByRef DataTypesCol As System.Collections.Specialized.NameValueCollection, _
                                     ByVal intIndex As Integer) As String
        Try
            Dim arrValues() As String
            arrValues = Split(DataTypesCol(DataTypesKey), ",")
            Return arrValues(intIndex)
        Catch
            Return ""
        End Try
    End Function

    Protected Sub chkForWHMCSAPI_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        If chkForWHMCSAPI.Checked Then
            InheritsTextbox.Text = _InheritsText
        Else
            InheritsTextbox.Text = ""
        End If
    End Sub
</script>
<html>
<head>
  <title><%=_Setting_Version%></title>

<style type="text/css">

.custompanel 
  { 
    font: 12pt verdana;
    background-color:#dddddd;
    border-color:#cccccc;
    border-width:1;
    border-style:solid;
    padding:20px;
  }

</style>  
  
</head>

<body style="font: 10pt verdana">

    <h3><%=_Setting_Version%></h3>

    <form id="Form1" runat="server">
        <div class="custompanel">
            <asp:CheckBox ID="chkForWHMCSAPI" runat="server" Checked="True" 
                Text="For Use with WHMCS API?" 
                oncheckedchanged="chkForWHMCSAPI_CheckedChanged" AutoPostBack="True" /><hr />
            Namespace: <asp:TextBox ID="txtNamespace" Runat="server" Text=""/>  
            Class Name: <asp:TextBox ID="txtClassName" Runat="server"/>
            &nbsp; Collection Plural:
            <asp:DropDownList ID="ddlPlural" Runat="server">
            <asp:ListItem Value="s">object[s]</asp:ListItem>
            <asp:ListItem Value="Collection" Selected>object[Collection]</asp:ListItem>
            </asp:DropDownList><br />
            
            Inherits: <asp:TextBox ID="InheritsTextbox" Runat="server" Text="" Width="300"/>  (Leave this blank normally)
            <hr/>
            
            Properties: (note: All properties are sortable with the collection.SortBy() and 
            collection.Sort() Methods)<br/>
            <asp:Label ID="lblError" runat="server" ForeColor="red" Text="" Visible="false"></asp:Label></br>
            <asp:placeholder id="plhProperties1" runat="server"></asp:placeholder>
            <br/>
            <asp:Button ID="btnAddProperty" Text="  Add Property >  " Runat="server" OnClick="btnAddProperty_Click"/>
            <hr/>
            Methods:<br/>
            <asp:placeholder id="plhMethods1" runat="server"></asp:placeholder>
            <br/>
            <asp:Button ID="btnAddMethod" Text="  Add Method >  " Runat="server" OnClick="btnAddMethod_Click"/>
            <hr/>
            <asp:CheckBox ID="chkForASP" runat="server" 
            Checked="True" Text="For ASP? (or VB.net when Unchecked)" />
            &nbsp;<asp:CheckBox ID="chkDebugEnabled" runat="server" Text="Include Debug Code?" 
            Checked="True" />

            <asp:Button ID="btnCreateClass" Text="  Create Class >>  " Runat="server" OnClick="btnCreateClass_Click"/><br/><br/>
            <asp:Label id="lblClassSaveAs" Runat="server" Visible="False"/><br/>
        </div>
        <br />
        <div class="custompanel">
            <textarea id="txtOutPut" cols="100" style="width:100%" rows="35" runat="server"></textarea>
        </div>
    </form>

	
  <div id="divClass1" runat="server" visible="false"/>

  <div id="divDebug" runat="server" visible="True"/>

</body>
</html>